/**
 * 分支及标签选择器
 * @param {boolean} needTagSearch 是否需要tag搜索，默认为需要
 * @param {string} subject 用于拼选择后跳转的url，默认为 window.FORCE.resourceSubject.subject
 * @param {func} onChange 用于自定义onChange事件
 * @param {boolean} noDefaultValue 用于指明是否不需要默认值,默认false
 * @param {boolean} autoComplete 用于指明是否输入内容,默认false
 * @return {element} 组件
 */

import React from 'react';
import { Select } from '@teamix/ui';
import remove from 'lodash.remove';
import exceed from 'utils/apimap';
import PropTypes from 'prop-types';
import Overlay from './overlay.jsx';
import { YunxiaoIcon, Title } from '@alife/devops-ui';
import KEYCODE from 'utils/keycode';
import './index.scss';
import intl from '../../locale';

const { pathResource, resourceSubject } = window.FORCE;

function preventDefault(e) {
  e.preventDefault();
}

export default class BranchAndTagSelect extends React.Component {
  static propTypes = {
    needTagSearch: PropTypes.bool,
    subject: PropTypes.string,
    onChange: PropTypes.func,
    noDefaultValue: PropTypes.bool,
    autoComplete: PropTypes.bool,
    autoWidth: PropTypes.bool,
    hasBorder: PropTypes.bool,
    value: PropTypes.string,
  };

  static defaultProps = {
    needTagSearch: true,
    subject: resourceSubject.subject,
    onChange: () => {},
    noDefaultValue: false,
    autoComplete: false,
    autoWidth: false,
    hasBorder: false,
    value: '',
  };

  constructor(props) {
    super(props);

    this.state = {
      branches: [],
      tags: [],
      value: !this.props.noDefaultValue ? resourceSubject.revision || 'master' : '',
      dataSource: [],
      isFetching: true,
      isLevelPopVisible: false,
      activeTab: 'branch',
    };
  }

  componentDidMount() {
    Promise.all([
      exceed.fetch({
        api: 'projects.all.branches.search',
        params: { id: pathResource.id },
        data: {
          sort: 'updated_desc',
        },
      }),

      exceed.fetch({
        api: 'project.tags',
        params: { projectId: pathResource.id },
        data: {
          page: 1,
          per_page: 100,
          show_signature: false,
        },
      }),
    ])
      .then((results) => {
        results[0].shift();
        results[1].shift();
        const branches = results[0];
        const tags = results[1];

        // 如果当前页面中有defaultBranch信息，且搜索结果中有defaultBranch，则将defaultBranch放到第一个
        if (pathResource.defaultBranch) {
          const [defaultBranchItem] = remove(
            branches,
            (item) => item.name === pathResource.defaultBranch,
          );

          if (defaultBranchItem) {
            branches.unshift(defaultBranchItem);
          }
        }

        const dataSource = this.getDataSource(branches, tags);
        this.setState({
          branches,
          tags,
          dataSource,
          isFetching: false,
        });
      })
      .catch((err) => {
        console.error(err);
      });
  }

  onChange = (value, actionType) => {
    // 对于Select.AutoComplete，actionType === 'change'时为搜索框中输入有变化
    if (actionType === 'change') {
      this.onSearch(value);
    }
    this.setState({
      value,
    });

    this.props.onChange(value);
  };

  onSearch = (q) => {
    const { branches, tags } = this.state;
    const filteredBranches = branches.filter((item) => item.name.includes(q));
    const filteredTags = tags.filter((item) => item.name.includes(q));

    const dataSource = this.getDataSource(filteredBranches, filteredTags);

    let visible = this.state.isLevelPopVisible;
    // 有匹配值时
    if (filteredBranches.length || filteredTags.length) {
      // 有搜索条件时,保持原有,没有搜索条件且面板关闭则将面板打开
      if (!q && !this.state.isLevelPopVisible) {
        visible = true;
      }
    } else {
      // 未匹配关闭面板
      visible = false;
    }
    const { isLevelPopVisible } = this.state;
    this.setState({
      dataSource,
      // 自动完成模式下才需要改变
      isLevelPopVisible: this.props.autoComplete ? visible : isLevelPopVisible,
    });
  };

  // 根据branches 和tags获取数据
  getDataSource = (branches = [], tags = []) => {
    const { needTagSearch } = this.props;
    const dataSource = [
      {
        // label: '最近更新',
        label: intl.get({
          id: 'code-assets.components.branchAndTagSelect.Branch',
          defaultMessage: '分支',
        }),
        children: [],
        key: 'branch',
      },
    ];

    if (branches && branches.length) {
      dataSource[0].children.push(
        ...branches.map((branch) => ({
          label: (
            <div className="branch-select-label">
              <div>
                <YunxiaoIcon type="branches-line" className="branch-select-label-icon" />
              </div>
              <Title
                trigger={<span className="branch-select-label-content">{branch.name}</span>}
                align="t"
              >
                {branch.name}
              </Title>
            </div>
          ),

          value: branch.name,
        })),
      );
    }
    if (tags && tags.length && needTagSearch) {
      dataSource.push({
        label: intl.get({
          id: 'code-assets.components.branchAndTagSelect.Label',
          defaultMessage: '标签',
        }),
        key: 'tag',
        children: tags.map((tag) => ({
          label: (
            <div className="branch-select-label">
              <div>
                <YunxiaoIcon type={'tag-line'} className="branch-select-label-icon" />
              </div>
              <Title
                trigger={
                  <span className="branch-select-label-content one-line-ellipsis">{tag.name}</span>
                }
                align="t"
              >
                {tag.name}
              </Title>
            </div>
          ),

          value: tag.name,
        })),
      });
    }
    // 调整顺序，如果分支和tag同名时，框内显示分支
    return dataSource.reverse();
  };

  handleSelect = (item) => {
    this.setState(
      {
        isLevelPopVisible: false,
        value: item.value,
      },
      () => {
        !this.props.autoComplete && this.onSearch('');
      },
    );

    this.props.onChange(item.value);
  };

  onVisibleChange = (visible) => {
    this.setState(
      {
        isLevelPopVisible: visible,
      },
      () => {
        this.resetData();
      },
    );
  };

  // 非autoComplete模式下，面板关闭后需要将过滤条件清空,显示所有数据
  resetData = () => {
    if (!this.props.autoComplete && !this.state.isLevelPopVisible) {
      this.onSearch('');
    }
  };

  changeActiveTab = (activeTab) => {
    this.setState({
      activeTab,
    });
  };

  handleKeyDown = (e) => {
    const { isLevelPopVisible } = this.state;
    switch (e.keyCode) {
      case KEYCODE.ENTER:
        e.preventDefault();
        this.setState(
          {
            isLevelPopVisible: !isLevelPopVisible,
          },
          () => {
            this.resetData();
          },
        );
        break;
      case KEYCODE.ESC:
        e.preventDefault();
        this.setState(
          {
            isLevelPopVisible: false,
          },
          () => {
            this.resetData();
          },
        );
        break;
      default:
        break;
    }
  };

  render() {
    const {
      needTagSearch,
      value,
      onChange,
      autoComplete,
      className,
      autoWidth,
      hasBorder,
      ...others
    } = this.props;
    const { dataSource, isFetching, activeTab } = this.state;
    let placeholderText = intl.get({
      id: 'code-assets.components.branchAndTagSelect.SearchForBranchesOrTags',
      defaultMessage: '搜索分支或标签',
    });
    if (!needTagSearch) {
      placeholderText = intl.get({
        id: 'code-assets.components.branchAndTagSelect.SearchForBranches',
        defaultMessage: '搜索分支',
      });
    }

    const visibilityPopupContent = (
      <Overlay
        onChange={this.handleSelect}
        onMouseDown={preventDefault}
        selectValue={value || this.state.value}
        data={dataSource}
        isOverlayLoading={isFetching}
        needTagSearch={needTagSearch}
        changeActiveTab={this.changeActiveTab}
        activeTab={activeTab}
      />
    );

    const popupProps = {
      triggerClickKeycode: [13, 32], // space, enter, down-arrow
    };

    if (autoComplete) {
      return (
        <Select.AutoComplete
          onChange={this.onChange}
          value={value || this.state.value}
          dataSource={dataSource}
          // style={{ maxWidth: 180 }}
          autoWidth={autoWidth}
          popupStyle={autoWidth ? {} : { width: 240 }}
          className={`branch-select ${className || ''}`}
          placeholder={placeholderText}
          visible={this.state.isLevelPopVisible}
          onVisibleChange={this.onVisibleChange}
          popupProps={popupProps}
          popupContent={visibilityPopupContent}
          onKeyDown={this.handleKeyDown}
          {...others}
        />
      );
    }

    // 无边框的情况，等数据请求完后再渲染，否则选中的样式会变化
    if (isFetching) {
      return null;
    }
    return (
      <Select
        onChange={this.onChange}
        value={value || this.state.value}
        dataSource={dataSource}
        showSearch
        style={{ maxWidth: 154 }}
        hasBorder={hasBorder}
        autoWidth={false}
        popupStyle={{ zIndex: 98 }}
        onSearch={this.onSearch}
        className={`branch-select no-border-select ${className || ''}`}
        placeholder={placeholderText}
        visible={this.state.isLevelPopVisible}
        onVisibleChange={this.onVisibleChange}
        popupProps={popupProps}
        popupContent={visibilityPopupContent}
        {...others}
      />
    );
  }
}
